<html><head>
      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
   <title>28.&nbsp;Cache Abstraction</title><link rel="stylesheet" href="css/stylesheet.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"><link rel="home" href="index.html" title="Reference Documentation"><link rel="up" href="spring-integration.html" title="Part&nbsp;VI.&nbsp;Integration"><link rel="prev" href="dynamic-language.html" title="27.&nbsp;Dynamic language support"><link rel="next" href="spring-appendices.html" title="Part&nbsp;VII.&nbsp;Appendices"><!--Begin Google Analytics code--><script type="text/javascript">
			var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
			document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
		</script><script type="text/javascript">
			var pageTracker = _gat._getTracker("UA-2728886-3");
			pageTracker._setDomainName("none");
			pageTracker._setAllowLinker(true);
			pageTracker._trackPageview();
		</script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">28.&nbsp;Cache Abstraction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="dynamic-language.html">Prev</a>&nbsp;</td><th width="60%" align="center">Part&nbsp;VI.&nbsp;Integration</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="spring-appendices.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="cache"></a>28.&nbsp;Cache Abstraction</h2></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cache-introduction"></a>28.1&nbsp;Introduction</h2></div></div></div><p>Since version 3.1, Spring Framework provides support for transparently
  	adding caching into an existing Spring application. Similar to the <a class="link" href="transaction.html" title="11.&nbsp;Transaction Management">transaction</a>
  	support, the caching abstraction allows consistent use of various caching
  	solutions with minimal impact on the code.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cache-strategies"></a>28.2&nbsp;Understanding the cache abstraction</h2></div></div></div><div class="sidebar"><p class="title"><b>Cache vs Buffer</b></p><p>The terms "buffer" and "cache" tend to be used interchangeably; note however they represent different things.
	A buffer is used traditionally as an intermediate temporary store for data between a fast and a slow entity. As one 
	party would have to <span class="emphasis"><em>wait</em></span> for the other affecting performance, the buffer alleviates this by
	allowing entire blocks of data to move at once rather then in small chunks. The data is written and read only once from
	the buffer.	Further more, the buffers are <span class="emphasis"><em>visible</em></span> to at least one party which is aware of it.</p><p>A cache on the other hand by definition is hidden and neither party is aware that caching occurs.It as well improves
	performance but does that by allowing the same data to be read multiple times in a fast fashion.</p><p>A further explanation of the differences between two can be found 
	<a class="ulink" href="http://en.wikipedia.org/wiki/Cache#The_difference_between_buffer_and_cache" target="_top">here</a>.</p></div><p>At its core, the abstraction applies caching to Java methods, reducing thus the number of executions based on the
	information available in the cache. That is, each time a <span class="emphasis"><em>targeted</em></span> method is invoked, the abstraction
	will apply a caching behaviour checking whether the method has been already executed for the given arguments. If it has,
	then the cached result is returned without having to execute the actual method; if it has not, then method is executed, the
	result cached and returned to the user so that, the next time the method is invoked, the cached result is returned.
	This way, expensive methods (whether CPU or IO bound) can be executed only once for a given set of parameters and the result
	reused without having to actually execute the method again. The caching logic is applied transparently without any interference
	to the invoker.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.gif"></td><th align="left">Important</th></tr><tr><td align="left" valign="top">Obviously this approach works only for methods that are guaranteed to return the same output (result) for a given input
	(or arguments) no matter how many times it is being executed.</td></tr></table></div><p>To use the cache abstraction, the developer needs to take care of two aspects:
	</p><div class="itemizedlist"><ul type="disc"><li>caching declaration - identify the methods that need to be cached and their policy</li><li>cache configuration - the backing cache where the data is stored and read from</li></ul></div><p>
	</p><p>Note that just like other services in Spring Framework, the caching service is an abstraction (not a cache implementation) and requires
	the use of an actual storage to store the cache data - that is, the abstraction frees the developer from having to write the caching
	logic but does not provide the actual stores. There are two integrations available out of the box, for JDK <code class="literal">java.util.concurrent.ConcurrentMap</code>
	and <a class="ulink" href="http://ehcache.org/" target="_top">Ehcache</a> - see <a class="xref" href="cache.html#cache-plug" title="28.5&nbsp;Plugging-in different back-end caches">Section&nbsp;28.5, &#8220;Plugging-in different back-end caches&#8221;</a> for more information on plugging in other cache stores/providers.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cache-annotations"></a>28.3&nbsp;Declarative annotation-based caching</h2></div></div></div><p>For caching declaration, the abstraction provides two Java annotations: <code class="literal">@Cacheable</code> and <code class="literal">@CacheEvict</code> which allow methods
	to trigger cache population or cache eviction. Let us take a closer look at each annotation:</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="cache-annotations-cacheable"></a>28.3.1&nbsp;<code class="literal">@Cacheable</code> annotation</h3></div></div></div><p>As the name implies, <code class="literal">@Cacheable</code> is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache
		so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. In its simplest form, 
		the annotation declaration requires the name of the cache associated with the annotated method:</p><pre class="programlisting">@Cacheable(<span class="hl-string">"books"</span>)
<span class="hl-keyword">public</span> Book findBook(ISBN isbn) {...}</pre><p>In the snippet above, the method <code class="literal">findBook</code> is associated with the cache named <code class="literal">books</code>. Each time the method is called, the cache
		is checked to see whether the invocation has been already executed and does not have to be repeated. While in most cases, only one cache is declared, the annotation allows multiple
		names to be specified so that more then one cache are being used. In this case, each of the caches will be checked before executing the method - if at least one cache is hit,
		then the associated value will be returned:</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">All the other caches that do not contain the method will be updated as well event though the cached method was not actually
		executed.</td></tr></table></div><pre class="programlisting">@Cacheable({ <span class="hl-string">"books"</span>, <span class="hl-string">"isbns"</span> })
<span class="hl-keyword">public</span> Book findBook(ISBN isbn) {...}</pre><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="cache-annotations-cacheable-default-key"></a>28.3.1.1&nbsp;Default Key Generation</h4></div></div></div><p>Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for cache access.
			Out of the box, the caching abstraction uses a simple <code class="interfacename">KeyGenerator</code> based on the following algorithm:</p><div class="itemizedlist"><ul type="disc"><li>If no params are given, return 0.</li><li>If only one param is given, return that instance.</li><li>If more the one param is given, return a key computed from the hashes of all parameters.</li></ul></div><p>
			This approach works well for objects with <span class="emphasis"><em>natural keys</em></span> as long as the <code class="literal">hashCode()</code> reflects that. If that is not the case then
			for distributed or persistent environments, the strategy needs to be changed as the objects hashCode is not preserved. 
			In fact, depending on the JVM implementation or running conditions, the same hashCode can be reused for different objects, in the same VM instance.</p><p>To provide a different <span class="emphasis"><em>default</em></span> key generator, one needs to implement the <code class="interfacename">org.springframework.cache.KeyGenerator</code> interface.
			Once configured, the generator will be used for each declaration that doesn not specify its own key generation strategy (see below).
			</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="cache-annotations-cacheable-key"></a>28.3.1.2&nbsp;Custom Key Generation Declaration</h4></div></div></div><p>Since caching is generic, it is quite likely the target methods have various signatures that cannot be simply mapped on top of the cache structure. This tends to become 
			obvious when the target method has multiple arguments out of which only some are suitable for caching (while the rest are used only by the method logic). For example:</p><pre class="programlisting">@Cacheable(<span class="hl-string">"books"</span>)
<span class="hl-keyword">public</span> Book findBook(ISBN isbn, <span class="hl-keyword">boolean</span> checkWarehouse, <span class="hl-keyword">boolean</span> includeUsed</pre><p>At first glance, while the two <code class="literal">boolean</code> arguments influence the way the book is found, they are no use for the cache. Further more what if only one of the two
			is important while the other is not?</p><p>For such cases, the <code class="literal">@Cacheable</code> annotation allows the user to specify how the key is generated through its <code class="literal">key</code> attribute.
			The developer can use <a class="link" href="expressions.html" title="7.&nbsp;Spring Expression Language (SpEL)">SpEL</a> to pick the arguments of interest (or their nested properties), perform operations or even invoke arbitrary methods without
			having to write any code or implement any interface. This is the recommended approach over the <a class="link" href="cache.html#cache-annotations-cacheable-default-key" title="28.3.1.1&nbsp;Default Key Generation">default</a> generator since
			methods tend to be quite different in signatures as the code base grows; while the default strategy might work for some methods, it rarely does for all methods.</p><p>
			Below are some examples of various SpEL declarations - if you are not familiar with it, do yourself a favour and read <a class="xref" href="expressions.html" title="7.&nbsp;Spring Expression Language (SpEL)">Chapter&nbsp;7, <i>Spring Expression Language (SpEL)</i></a>: 			
			</p><pre class="programlisting">
@Cacheable(value=<span class="hl-string">"book"</span>, key=<span class="hl-string">"#isbn"</span>
<span class="hl-keyword">public</span> Book findBook(ISBN isbn, <span class="hl-keyword">boolean</span> checkWarehouse, <span class="hl-keyword">boolean</span> includeUsed)


@Cacheable(value=<span class="hl-string">"book"</span>, key=<span class="hl-string">"#isbn.rawNumber"</span>)
<span class="hl-keyword">public</span> Book findBook(ISBN isbn, <span class="hl-keyword">boolean</span> checkWarehouse, <span class="hl-keyword">boolean</span> includeUsed)


@Cacheable(value=<span class="hl-string">"book"</span>, key=<span class="hl-string">"T(someType).hash(#isbn)"</span>)
<span class="hl-keyword">public</span> Book findBook(ISBN isbn, <span class="hl-keyword">boolean</span> checkWarehouse, <span class="hl-keyword">boolean</span> includeUsed)</pre><p>The snippets above, show how easy it is to select a certain argument, one of its properties or even an arbitrary (static) method.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="cache-annotations-cacheable-condition"></a>28.3.1.3&nbsp;Conditional caching</h4></div></div></div><p>Sometimes, a method might not be suitable for caching all the time (for example, it might depend on the given arguments). The cache annotations support such functionality
			through the <code class="literal">conditional</code> parameter which takes a <code class="literal">SpEL</code> expression that is evaluated to either <code class="literal">true</code> or <code class="literal">false</code>.
			If <code class="literal">true</code>, the method is cached - if not, it behaves as if the method is not cached, that is executed every since time no matter what values are in the cache or what
			arguments are used. A quick example - the following method will be cached, only if the argument <code class="literal">name</code> has a length shorter then 32:</p><pre class="programlisting">@Cacheable(value=<span class="hl-string">"book"</span>, condition=<span class="hl-string">"#name.length &lt; 32"</span>)
<span class="hl-keyword">public</span> Book findBook(String name)</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="cache-spel-context"></a>28.3.1.4&nbsp;Available caching <code class="literal">SpEL</code> evaluation context</h4></div></div></div><p>Each <code class="literal">SpEL</code> expression evaluates again a dedicated <code class="literal"><a class="link" href="expressions.html#expressions-language-ref" title="7.5&nbsp;Language Reference">context</a></code>. In addition
			to the build in parameters, the framework provides dedicated caching related metadata such as the argument names. The next table lists the items made available to the context
			so one can use them for key and conditional(see next section) computations:</p><div class="table"><a name="cache-spel-context-tbl"></a><p class="title"><b>Table&nbsp;28.1.&nbsp;Cache SpEL available metadata</b></p><div class="table-contents"><table summary="Cache SpEL available metadata" width="100%" style="border-collapse: collapse;border-top: 1.0pt solid ; border-bottom: 1.0pt solid ; border-left: 1.0pt solid ; border-right: 1.0pt solid ; "><colgroup><col align="center"><col><col><col></colgroup><thead><tr><th style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">Name</th><th style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">Location</th><th style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">Description</th><th style="border-bottom: 1.0pt solid ; ">Example</th></tr></thead><tbody><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">methodName</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">root object</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">The name of the method being invoked</td><td style="border-bottom: 1.0pt solid ; "><pre class="screen">#root.methodName</pre></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">method</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">root object</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">The method being invoked</td><td style="border-bottom: 1.0pt solid ; "><pre class="screen">#root.method.name</pre></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">target</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">root object</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">The target object being invoked</td><td style="border-bottom: 1.0pt solid ; "><pre class="screen">#root.target</pre></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">targetClass</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">root object</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">The class of the target being invoked</td><td style="border-bottom: 1.0pt solid ; "><pre class="screen">#root.targetClass</pre></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">params</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">root object</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">The arguments (as array) used for invoking the target</td><td style="border-bottom: 1.0pt solid ; "><pre class="screen">#root.params[0]</pre></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; " align="center">caches</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">root object</td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">Collection of caches against which the current method is executed</td><td style="border-bottom: 1.0pt solid ; "><pre class="screen">#root.caches[0].name</pre></td></tr><tr><td style="border-right: 1.0pt solid ; " align="center"><span class="emphasis"><em>parameter name</em></span></td><td style="border-right: 1.0pt solid ; ">evaluation context</td><td style="border-right: 1.0pt solid ; ">Name of any of the method parameter. If for some reason the names are not available (ex: no debug information),
					  	the parameter names are also available under the <code class="literal">p&lt;#arg&gt;</code> where 
					  	<span class="emphasis"><em>#arg</em></span> stands for the parameter index (starting from 0).</td><td style=""><pre class="screen">iban</pre> or <pre class="screen">p0</pre></td></tr></tbody></table></div></div><br class="table-break"></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="cache-annotations-evict"></a>28.3.2&nbsp;<code class="literal">@CacheEvict</code> annotation</h3></div></div></div><p>The cache abstraction allows not just population of a cache store but also eviction. This process is useful for removing stale or unused data from the cache. Opposed to 
		<code class="literal">@Cacheable</code>, annotation <code class="literal">@CacheEvict</code> demarcates methods that perform cache <span class="emphasis"><em>eviction</em></span>, that is methods that act as triggers
		for removing data from the cache. Just like its sibling, <code class="literal">@CacheEvict</code> requires one to specify one (or multiple) caches that are affected by the action, allows a
		key or a condition to be specified but in addition, features an extra parameter <code class="literal">allEntries</code> which indicates whether a cache-wide eviction needs to be performed
		rather then just an entry one (based on the key):</p><pre class="programlisting">@CacheEvict(value = <span class="hl-string">"books"</span>, allEntries=true)
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> loadBooks(InputStream batch)</pre><p>This option comes in handy when an entire cache region needs to be cleared out - rather then evicting each entry (which would take a long time since it is inefficient), 
		all the entires are removed in one operation as shown above. Note that the framework will ignore any key specified in this scenario as it does not apply (the entire cache is evicted not just
		one entry).</p><p>It is important to note that void methods can be used with <code class="literal">@CacheEvict</code> - as the methods act as triggers, the return values are ignored (as they don't interact with
		the cache) - this is not the case with <code class="literal">@Cacheable</code> which adds/update data into the cache and thus requires a result.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="cache-annotation-enable"></a>28.3.3&nbsp;Enable caching annotations</h3></div></div></div><p>It is important to note that even though declaring the cache annotations does not automatically triggers their actions - like many things in Spring, the feature has to be declaratively
		enabled (which means if you ever suspect caching is to blame, you can disable it by removing only one configuration line rather then all the annotations in your code). In practice, this
		translates to one line that informs Spring that it should process the cache annotations, namely:</p><pre class="programlisting">&lt;<span class="hl-tag">beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span> <span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="hl-attribute">xmlns:cache</span>=<span class="hl-value">"http://www.springframework.org/schema/cache"</span>
  <span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"</span>&gt;
  &lt;<span class="hl-tag">cache:annotation-driven</span> /&gt;
&lt;<span class="hl-tag">/beans</span>&gt;</pre><p>The namespace allows various options to be specified that influence the way the caching behaviour is added to the application through AOP. The configuration is similar (on purpose)
		with that of <code class="literal"><a class="ulink" href="tx-annotation-driven-settings" target="_top">tx:annotation-driven</a></code>:
		</p><div class="table"><a name="cache-annotation-driven-settings"></a><p class="title"><b>Table&nbsp;28.2.&nbsp;<code class="literal">&lt;cache:annotation-driven/&gt;</code>
          settings</b></p><div class="table-contents"><table summary="<cache:annotation-driven/&gt;&#xA;          settings" style="border-collapse: collapse;border-top: 1.0pt solid ; border-bottom: 1.0pt solid ; border-left: 1.0pt solid ; border-right: 1.0pt solid ; "><colgroup><col><col><col></colgroup><thead><tr><th style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">Attribute</th><th style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">Default</th><th style="border-bottom: 1.0pt solid ; ">Description</th></tr></thead><tbody><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; "><code class="literal">cache-manager</code></td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">cacheManager</td><td style="border-bottom: 1.0pt solid ; "><p>Name of cache manager to use. Only required
                if the name of the cache manager is not
                <code class="literal">cacheManager</code>, as in the example
                above.</p></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; "><code class="literal">mode</code></td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">proxy</td><td style="border-bottom: 1.0pt solid ; "><p>The default mode "proxy" processes annotated
                beans to be proxied using Spring's AOP framework (following
                proxy semantics, as discussed above, applying to method calls
                coming in through the proxy only). The alternative mode
                "aspectj" instead weaves the affected classes with Spring's
                AspectJ caching aspect, modifying the target class byte
                code to apply to any kind of method call. AspectJ weaving
                requires spring-aspects.jar in the classpath as well as
                load-time weaving (or compile-time weaving) enabled. (See
                <a class="xref" href="aop.html#aop-aj-ltw-spring" title="8.8.4.5&nbsp;Spring configuration">Section&nbsp;8.8.4.5, &#8220;Spring configuration&#8221;</a> for details on how to set
                up load-time weaving.)</p></td></tr><tr><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; "><code class="literal">proxy-target-class</code></td><td style="border-right: 1.0pt solid ; border-bottom: 1.0pt solid ; ">false</td><td style="border-bottom: 1.0pt solid ; "><p>Applies to proxy mode only. Controls what type of
                caching proxies are created for classes annotated with
                the <code class="interfacename">@Cacheable</code> or <code class="interfacename">@CacheEvict</code> annotations.
                If the <code class="literal">proxy-target-class</code> attribute is set
                to <code class="literal">true</code>, then class-based proxies are
                created. If <code class="literal">proxy-target-class</code> is
                <code class="literal">false</code> or if the attribute is omitted, then
                standard JDK interface-based proxies are created. (See <a class="xref" href="aop.html#aop-proxying" title="8.6&nbsp;Proxying mechanisms">Section&nbsp;8.6, &#8220;Proxying mechanisms&#8221;</a> for a detailed examination of the
                different proxy types.)</p></td></tr><tr><td style="border-right: 1.0pt solid ; "><code class="literal">order</code></td><td style="border-right: 1.0pt solid ; ">Ordered.LOWEST_PRECEDENCE</td><td style=""><p>Defines the order of the cache advice that
                is applied to beans annotated with
                <code class="interfacename">@Cacheable</code> or <code class="interfacename">@CacheEvict</code>. 
                (For more
                information about the rules related to ordering of AOP advice,
                see <a class="xref" href="aop.html#aop-ataspectj-advice-ordering" title="8.2.4.7&nbsp;Advice ordering">Section&nbsp;8.2.4.7, &#8220;Advice ordering&#8221;</a>.) No
                specified ordering means that the AOP subsystem determines the
                order of the advice.</p></td></tr></tbody></table></div></div><p><br class="table-break"></p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">&lt;cache:annotation-driven/&gt;</code> only looks for
        <code class="interfacename">@Cacheable/@CacheEvict</code> on beans in the same
        application context it is defined in. This means that, if you put
        <code class="literal">&lt;cache:annotation-driven/&gt;</code> in a
        <code class="interfacename">WebApplicationContext</code> for a
        <code class="classname">DispatcherServlet</code>, it only checks for
        <code class="interfacename">@Cacheable/@CacheEvict</code> beans in your
        controllers, and not your services. See <a class="xref" href="mvc.html#mvc-servlet" title="16.2&nbsp;The DispatcherServlet">Section&nbsp;16.2, &#8220;The DispatcherServlet&#8221;</a> for more information.</p></td></tr></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="cache-annotation-stereotype"></a>28.3.4&nbsp;Using custom annotations</h3></div></div></div><p>The caching abstraction allows one to use her own annotations to identify what method trigger cache population or eviction. This is quite handy as a template mechanism as it eliminates
		the need to duplicate cache annotation declarations (especially useful if the key or condition are specified) or if the foreign imports (<code class="literal">org.springframework</code>) are not allowed
		in your code base. Similar to the rest of the <a class="link" href="beans.html#beans-stereotype-annotations" title="4.10.1&nbsp;@Component and further stereotype annotations">stereotype</a> annotations, both <code class="literal">@Cacheable</code> and <code class="literal">@CacheEvict</code>
		can be used as meta-annotations, that is annotations that can annotate other annotations. To wit, let us replace a common <code class="literal">@Cacheable</code> declaration with our own, custom 
		annotation: 
		</p><pre class="programlisting">@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(value=&#8220;books&#8221;, key=<span class="hl-string">"#isbn"</span>)
<span class="hl-keyword">public</span> @<span class="hl-keyword">interface</span> SlowService {
}</pre><p>Above, we have defined our own <code class="literal">SlowService</code> annotation which itself is annotated with <code class="literal">@Cacheable</code> - now we can replace the following code:</p><pre class="programlisting">@Cacheable(value=<span class="hl-string">"books"</span>, key=<span class="hl-string">"#isbn"</span>)
<span class="hl-keyword">public</span> Book findBook(ISBN isbn, <span class="hl-keyword">boolean</span> checkWarehouse, <span class="hl-keyword">boolean</span> includeUsed)</pre><p>with:</p><pre class="programlisting">@SlowService
<span class="hl-keyword">public</span> Book findBook(ISBN isbn, <span class="hl-keyword">boolean</span> checkWarehouse, <span class="hl-keyword">boolean</span> includeUsed)</pre><p>Even though <code class="literal">@SlowService</code> is not a Spring annotation, the container automatically picks up its declaration at runtime and understands its meaning. Note that as
		mentined <a class="link" href="cache.html#cache-annotation-enable" title="28.3.3&nbsp;Enable caching annotations">above</a>, the annotation-driven behaviour needs to be enabled.</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cache-store-configuration"></a>28.4&nbsp;Configuring the cache storage</h2></div></div></div><p>Out of the box, the cache abstraction provides integration with two storages - one on top of the JDK <code class="interfacename">ConcurrentMap</code> and one 
	for <a class="ulink" href="ehcache.org" target="_top">ehcache</a> library. To use them, one needs to simply declare an appropriate <code class="interfacename">CacheManager</code> - an entity that controls and manages
	<code class="interfacename">Cache</code>s and can be used to retrieve these for storage.</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="cache-store-configuration-jdk"></a>28.4.1&nbsp;JDK <code class="interfacename">ConcurrentMap</code>-based <code class="interfacename">Cache</code></h3></div></div></div><p>The JDK-based <code class="interfacename">Cache</code> implementation resides under <code class="literal">org.springframework.cache.concurrent</code> package. It allows one to use <code class="classname">
		ConcurrentHashMap</code> as a backing <code class="interfacename">Cache</code> store.</p><pre class="programlisting">&lt;<span class="hl-comment">!-- generic cache manager --</span>&gt;
&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"cacheManager"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.cache.support.SimpleCacheManager"</span>&gt;
  &lt;<span class="hl-tag">property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"caches"</span>&gt;
    &lt;<span class="hl-tag">set</span>&gt;
      &lt;<span class="hl-tag">bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"</span> <span class="hl-attribute">p:name</span>=<span class="hl-value">"default"</span>/&gt;
      &lt;<span class="hl-tag">bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"</span> <span class="hl-attribute">p:name</span>=<span class="hl-value">"books"</span>/&gt;
    &lt;<span class="hl-tag">/set</span>&gt;
  &lt;<span class="hl-tag">/property</span>&gt;
&lt;<span class="hl-tag">/bean</span>&gt;</pre><p>The snippet above uses the <code class="classname">SimpleCacheManager</code> to create a <code class="interfacename">CacheManager</code> for the two, nested <code class="interfacename">Concurrent</code>
		<code class="interfacename">Cache</code> implementations named <span class="emphasis"><em>default</em></span> and <span class="emphasis"><em>books</em></span>. 
		Note that the names are configured directly for each cache.</p><p>As the cache is created by the application, it is bound to its lifecycle, making it suitable for basic use cases, tests or simple applications. The cache scales well and is very fast
		but it does not provide any management or persistence capabilities nor eviction contracts.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="cache-store-configuration-ehcache"></a>28.4.2&nbsp;Ehcache-based <code class="interfacename">Cache</code></h3></div></div></div><p>The Ehcache implementation is located under <code class="literal">org.springframework.cache.ehcache</code> package. Again, to use it, one simply needs to declare the appropriate 
		<code class="interfacename">CacheManager</code>:</p><pre class="programlisting">&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"cacheManager"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.cache.ehcache.EhcacheCacheManager"</span> <span class="hl-attribute">p:cache-manager</span>=<span class="hl-value">"ehcache"</span>/&gt;

&lt;<span class="hl-comment">!-- Ehcache library setup --</span>&gt;
&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"ehcache"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.cache.ehcache.EhCacheManagerFactoryBean"</span> <span class="hl-attribute">p:config-location</span>=<span class="hl-value">"ehcache.xml"</span>/&gt;</pre><p>This setup bootstraps ehcache library inside Spring IoC (through bean <code class="literal">ehcache</code>) which is then wired into the dedicated <code class="interfacename">CacheManager</code>
		implementation. Note the entire ehcache-specific configuration is read from the resource <code class="literal">ehcache.xml</code>.</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cache-plug"></a>28.5&nbsp;Plugging-in different back-end caches</h2></div></div></div><p>Clearly there are plenty of caching products out there that can be used as a backing store. To plug them in, one needs to provide a <code class="interfacename">CacheManager</code> and
	<code class="interfacename">Cache</code> implementation since unfortunately there is no available standard that we can use instead. This may sound harder then it is since in practice, 
	the classes tend to be simple <a class="ulink" href="http://en.wikipedia.org/wiki/Adapter_pattern" target="_top">adapter</a>s that map the caching abstraction framework on top of the storage API as the <code class="literal">ehcache</code> classes can show.
	Most <code class="interfacename">CacheManager</code> classes can use the classes in <code class="literal">org.springframework.cache.support</code> package, such as <code class="classname">AbstractCacheManager</code>
	which takes care of the boiler-plate code leaving only the actual <span class="emphasis"><em>mapping</em></span> to be completed. We hope that in time, the libraries that provide integration with Spring 
	can fill in this small configuration gap.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
			_lf_cid = "LF_48be82fa";
			_lf_remora();
		</script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="dynamic-language.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="spring-integration.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="spring-appendices.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">27.&nbsp;Dynamic language support&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Part&nbsp;VII.&nbsp;Appendices</td></tr></table></div></body></html>